home *** CD-ROM | disk | FTP | other *** search
- Path: solon.com!not-for-mail
- From: seebs@solutions.solon.com (Peter Seebach)
- Newsgroups: comp.lang.c.moderated,comp.lang.c,comp.std.c
- Subject: Re: Perhaps it's time the C community *did* something about bad books.
- Date: 25 Jan 1996 21:06:23 -0600
- Organization: Usenet Fact Police (Undercover)
- Approved: seebs
- Message-ID: <4e9gff$9n9@solutions.solon.com>
- References: <4e07lv$adu@solutions.solon.com> <4e5ooa$6b5@solutions.solon.com> <4e9f08$9br@solutions.solon.com>
- NNTP-Posting-Host: solutions.solon.com
-
- In article <4e9f08$9br@solutions.solon.com>,
- Scott McMahan - Softbase Systems <softbase@mercury.interpath.com> wrote:
- >Not exactly. This is actually the review of the ANSI C standard.
- >The "review" errs on the side of being way too critical, and I've
- >seen it being debunked in part, but the parts that are debunked
- >never seem to be posted with the review anywhere. It's one of those
- >things that will endure forever.
-
- Well, I went through it, and I saw nothing in it that was incorrect.
- I have the annotated standard, and it's pretty poorly annotated, IMHO.
-
- >I did not see the post that listed errors in C: TCR. I'm interested
- >in reading it.
-
- I didn't list them, I just said there were some. It's about 8k/250
- lines, and it is pathetically far from complete. In a letter to the
- editor at O-MGH, I mentioned several types of errors, so I found about
- 2-5 examples of each. It took about 45 minutes, including skimming
- trying to find an offensively bad misstatement of how precedence
- works, which claims that
- x = *p * (*p++);
- is legal. (And not even because of the parens, but rather, because
- it's on the right. Despite the correct statement about OOE earlier.)
-
- >I agree that we should all make Osborne aware of all the errors in
- >Mr. Schildt's book so that he can make them better in future
- >editions. I was very disappointed in the 3rd Ed. compared to
- >the 2nd.
-
- He corrected at least one error; on or about page 53, the 2nd edition
- had "i <> 1" and the 3rd has "i != 1".
-
- >On the other hand,
- >the third edition seems to have been released in extreme secrecy since I
- >learned about it only though a McGraw-Hill book-of-the-month club ad.
-
- I agree; I only saw it last week in a bookstore for the first time.
-
- >What's new? The third edition is surprisingly unchanged. Instead of
- >taking the chance to reflect on which chapters he has written in his
- >almost 10 years of writing on C and picking the ones that would be most
- >useful to an ANSI C programmer, Schildt has instead placed chapters that
- >have little to do with a complete reference, including a tacky
- >self-promotion.
-
- This is sadly true; a large number of obvious errors have survived.
-
- Some are simply utterly stupid; the claim that you must use feof() to
- detect EOF on a binary file, since "EOF is an integer". (Just like
- the ones returned by getchar(), which spends the entire book being
- returned into a char.) I will not insult the intelligence of the
- reader by explaining this, suffice it to say I nearly fell out of
- my chair laughing at it.
-
- >Unless Schildt starts trying to find what people want and starts
- >remembering why he wrote C: The Complete Reference in the first place,
- >he and Osborne are going to have a hard time selling books with ads for
- >other books instead of content and using Schildt's name. Schildt is
- >already known as a schmuck among real C programmers, deservedly or not,
- >and pretty soon everyone will be calling him the "recognized authority"
- >on self-promotion and hot air. Either Schildt or McGraw-Hill appears to
- >be damaging Schildt's already very shakey reputation beyond repair for
- >small short-term gain. I don't know why, is Osborne in some kind of
- >financial trouble? They should be trying to build a reputation for
- >quality.
-
- *sigh*
-
- A minor nit; he lists quicksort as generally the best sort known.
-
- I have written the publisher a list (enclosed at the bottom of this
- post) of errors, and pointed out that this is really bad. The editor
- I corresponded with (scottr@crl.com) said he'd run these by Herb to
- see if Schildt would appreciate a bit of technical editing.
-
- I have been informed that they are no longer using the technical editor
- who was involved with this book, which really doesn't explain how
- this garbage survived 3 editions.
-
- >Unfortunately for me, I will probably never order another edition of
- >this book, unless the concerns raised here are directly addressed. I'm
- >very disenchanted with this book, and will look elsewhere for my
- >reference material.
-
- I would never have gotten it if I weren't planning to offer the publisher
- "reasonable" rates on the technical editing the book desperately needs.
- Feel free to write the editor with comments, positive or negative,
- about my ability to improve on this work. (Or me, for that matter.)
-
- Enclosed please find the (mildly vitriolic in places) comments I have
- on a representative set of examples. I am far from exhasting what I
- saw; I just wanted a good representative set.
-
- Newbies to C: Take the time to read through these, especially if you
- have the book. Some of these errors could cost you hours or days of
- trying to figure out a problem.
-
- ---
-
- I am not including "bad style", but there are a few of those (gets is
- strongly depracated, and many programs don't output the last newline,
- probably because MS-DOS prints an extra one before the prompt.)
-
- Please pardon typos, and even the possible errors; I have not taken the time
- to verify a couple of things. For a serious, aimed-at-publication effort,
- I would, of course, take the time to bring the questionable points to the
- attention of people in comp.std.c, or otherwise cross-reference the work.
- As is, I'm just using memory and the Standard to compare.
-
- Flat contradictions of ANSI's standard.
-
- Page 163
-
- "You may also declare main() as void if it does
- not return a value."
-
- Specifically untrue. ANSI mandates two declarations for main, and
- says that main may have declarations compatible with those. Both
- return int.
-
- Page 434
-
- "free() must only be called with a pointer that was
- previously allocated with one of the dynamic allocation
- system's functions (either malloc(), realloc(), or
- calloc())."
-
- Also specifically untrue. ANSI states that free(NULL) is legal and
- has no effect. (Also note that it must be called with a pointer
- *to space previously allocated*, not with a pointer previously
- allocated, and that the pointer must not have been already freed
- or passed to realloc().)
-
- Page 314
-
- "However, since EOF is a valid integer value, you must use
- feof() to check for end-of-file when working with binary
- files."
-
- Not merely a little bit untrue, but utterly wrong, and specifically
- missing the point of the rule (correctly stated) about returning
- the char as "unsigned char converted to int" (actually stated
- in the standard in 7.9.7.1, under fgetc()).
-
- Since EOF is a *NEGATIVE* integral constant, it can *NEVER* compare
- equal to *ANY* unsigned char. When you are reading from a binary
- file, the values you get will *never* compare equal to EOF, until
- getchar() returns EOF because the file is empty.
-
- This correlates with a mistake made in all of the examples where
- loops break on '$', 'A', or ' ' because the return from getchar() is
- immediately put into a char variable.
-
- This is a more serious flaw than many, because it results in poorly
- written, inefficient code.
-
- (Couple this with the consistent attempts to use feof() to see if
- the *next* read will fail, when in fact feof() only returns true
- when the *PREVIOUS* read failed, and you get a completely wrong
- description of the standard I/O library.)
-
- Also, several of the programs given loop forever if an end of
- file is reached, because EOF is not checked for in a loop.
-
- Page 284
-
- All of the header files are listed in capitals; the standard
- specifies them in lower case. It is not required that a
- C compiler reject all-caps, but nor is it required that it
- accept them.
-
- Flat contradictions of POSIX, in the discussion of open/read/write.
-
- Page 253
-
- "In most implementations, the operation fails if the file
- specified in the open statement does not exist on the disk."
-
- To the best of my knowledge, POSIX (the standard for the open()
- call) documents and requires the functionality of the O_CREAT flag.
-
- [I spelled that as "C_CREAT" in the original. Oops. -seebs]
-
- Undefined behavior/illegal code.
-
- Page 247
-
- The stream fp is opened with mode "r", the mode to open a text file.
- Then, fseek is called on fp, with the 2nd argument not a value
- returned by a previous call to ftell. (ANSI 7.9.9.2, "For a text
- stream, either offset shall be zero, or offset shall be a value
- returned by an earlier call to the ftell function on the same stream
- and whence shall be SEEK_SET.")
-
- Page 63
-
- If scanf fails, the variable guess is referenced before it has been
- initialized; accessing an uninitialized object introduces
- undefined behavior.
-
- Page 283
-
- >#include <string.h>
- >
- >char s1[] = "hello ";
- >char s2[] = "there.";
- >
- >void main(void)
- >{
- > int p;
- >
- > p = strcat(s1, s2);
- >}
-
- It is correctly noted that this generates a warning. Not mentioned
- is that it's illegal; although s1[] is a modifiable array, it is
- an array large enough to hold "hello " (and the terminating NUL),
- so it has room for 7 bytes. The strcat overflows the array, producing
- undefined behavior.
-
- Page 735
-
- This is spectacularly wrong; the "corrected"
-
- "x = *p * (*p++);"
-
- is *EXACTLY* equivalent in terms of C; as correctly noted earlier,
- the order of evaluation *IS NOT SPECIFIED*.
-
- The code is still illegal (p is used to determine *p on the left
- of the *, as well as modified on the right), and the parentheses
- aren't affecting the code at all.
-
- In this code, p can be incremented anywhere in the line; the only
- requirement would be that the value of (*p++) be the same as
- the value of (*p) before the increment. It is *not* specified
- whether the other *p happens before or after the increment.
-
- In fact, because the code modifies an object (p) and uses the value
- of the object to do something other than determine the new value
- (The first "*p"), it is *illegal*. Completely; a compiler is allowed
- to reject the code, and many will produce surprising results from
- this operation.
-
- This is not merely wrong, it's wrong *while discussing the problem*,
- which is doubly bad.
-
- Code which does not do what it says it does.
-
- Page 333
-
- >sprintf("%s %d %c", "one", 2, 3);
-
- The result would be "one 2 " and then a control-c, not "one 2 3".
- (Presumably, "3" should have been "'3'".)
-
- Page 53
-
- >printf("%f", sizeof f);
-
- Clearly wrong; sizeof is not a double or float.
-
- Page 53
-
- >printf("%d", sizeof(int));
-
- Subtly wrong; sizeof is a size_t, which may not be any sort of int.
- The only safe way to do this is
-
- >printf("%ul", (unsigned long) sizeof(int));
-
- While this is larger, a clear explanation of why it is required will
- go a long way towards helping people understand C.
-
- Page 53 (This one's popular)
-
- >/* Write 6 integers to a disk file. */
- >void put_rec(int rec[6], FILE *fp)
- >{
- > int len;
- >
- > len = fwrite(rec, sizeof rec, 1, fp);
- > if (len != 1) printf("write error");
- >}
-
- Incorrect. As correctly noted elsewhere, when "int rec[6]" is an
- argument to a function, it actually specifies a pointer-to-int,
- not an array[6]-of-int. sizeof rec is sizeof(int *) here, and this
- code works only if sizeof(int *) is precisely 6 times sizeof(int).
- (Not impossible, but hardly likely.)
-
- Further, who said fp was a disk file? fp could be stdout.
-
- Inaccurate or misleading explanations.
-
- Page 132
-
- "After the assignment, p points to the first 1000 bytes of
- free memory."
-
- No, p points to at least 1000 bytes of allocated space, which is
- not free memory. There is also no reason to assume it was the
- "first" 1000 bytes; top-down allocation is not atypical, and
- further, there's no reason to assume this code fragment runs in
- isolation.
-
- Page 197
-
- It is redundant to give a size of char in bytes as 1 as an
- "assumption" - it's the definition, sizeof() gives the size
- in *chars*.
-
- Page 162
-
- Functions are not of type void; functions are of various types,
- called collectively the function types. A function may have a
- return of type void, which means that its type is something like
- "function taking (...) and returning void".
-
- Page 59
-
- "This shorthand works for all the binary operators..."
-
- [Meaning op=, ala +=, -=... -seebs]
- No, it doesn't. It doesn't work for ".", "->", "&&", or "||".
-
- Page 33
-
- "static Global Variables" [heading]
-
- No such thing. A static variable outside of a function has file
- scope, which is distinct from global scope.
-
- Explanations of a DOS-specific feature as "how C works".
-
- Page 19
-
- "In general, negative numbers are represented using the
- two's complement approach..."
-
- This is not a C feature. It is a common implementation, but it is
- specifically not required.
-
- Page 131
-
- "Memory allocated by C's dynamic allocation functions is
- obtained from the <i>heap</i> -- the region of free memory
- that lies between your program and its permanent storage
- area and the stack."
-
- C does not specify that there is a stack - only that functions can
- call each other. The "heap" is a DOS term, and the layout is not
- a part of the C language. It is not atypical for the layout to be
- radically different, and certainly, there is no call for describing
- a specific choice as "what happens".
-
-
- ---cut here
-
- *sigh*
-
- -seebs
- (still hypothetically working on my own reference manual, but the chances
- of my getting anywhere until I have enough money and time are quite low.
- Donations cheerfully accepted. <- blatant plug!)
- --
- Peter Seebach - seebs@solon.com - Copyright 1995 Peter Seebach.
- C/Unix proto-wizard -- C/Unix questions? Send mail for help. No, really!
- Using trn? Weird new newsgroup problem? I know the fix! Email me!
- The *other* C FAQ - ftp taniemarie.solon.com /pub/c/afq - Not A Flying Toy
-